package com.tiger.userClient.http.auth;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiger.db.entity.OtherUser;
import com.tiger.db.entity.Student;
import com.tiger.db.entity.Teacher;
import com.tiger.db.entity.Users;
import com.tiger.mongodb.entity.PortalLoginLog;
import com.tiger.mongodb.repository.PortalLoginLogRepository;
import com.tiger.userClient.Db;
import com.tiger.userClient.http.auth.dto.LoginDto;
import com.tiger.userClient.http.auth.type.UserRoleType;
import com.tiger.userClient.caspOpeapi.Openapi;
import com.tiger.userClient.type.WechatConfig;
import com.tiger.userClient.wechatapi.Wechatapi;
import com.tiger.utils.IpUtil;
import com.tiger.utils.ResponseUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apereo.cas.client.util.AbstractCasFilter;
import org.apereo.cas.client.validation.Assertion;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;


import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping("/auth")
public class AuthController {
    private static final String authStatusKey = "authStatus";

    private final Wechatapi wechatapi;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Value("${casAuthServerLogout}")
    private String logoutUrl;

    @Value("${APP_HOST}")
    private String APP_HOST;

    private final WechatConfig wechatConfig;

    private final Openapi openapi;

    private final AuthService authService;

    private final Db db;
    private final PortalLoginLogRepository userLoginLogRepository;

    public AuthController(Wechatapi wechatapi, WechatConfig wechatConfig, Openapi openapi, AuthService authService, Db db, PortalLoginLogRepository userLoginLogRepository) {
        this.wechatapi = wechatapi;
        this.wechatConfig = wechatConfig;
        this.openapi = openapi;
        this.authService = authService;
        this.db = db;
        this.userLoginLogRepository = userLoginLogRepository;
    }

    @GetMapping("location")
    public void location(HttpServletRequest request, HttpServletResponse response) throws IOException {
        authService.ipToLogin(IpUtil.getIpAddr(request));
    }

    @GetMapping("status")
    public Object status(HttpSession httpSession) {
        if(httpSession.getAttribute(authStatusKey) != null) {
            Map<String, Object> res = new HashMap<>();
            res.put("role", httpSession.getAttribute("role"));
            res.put("userInfo", httpSession.getAttribute("userInfo"));

            return ResponseUtil.successRes(res);
        }

        return ResponseUtil.failRes();
    }


    @GetMapping("wechat")
    public void wechatAuth(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //System.out.println(request.getRequestURL().toString());
        String forwardedProto = request.getHeader("X-Forwarded-Proto");
        //System.out.println("X-Forwarded-Proto: " + forwardedProto);

        URL urlObj = new URL(request.getRequestURL().toString());
        String protocol = urlObj.getProtocol(); // 获取协议（如http, https）
        String host = urlObj.getHost(); // 获取主机名（域名）
        String redirectUrl = protocol + "://" + host;

        redirectUrl = APP_HOST;

        if(!contextPath.isEmpty()) {
            redirectUrl += contextPath;
        }

        redirectUrl += "/auth/wechat/redirect/";
        redirectUrl = URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8);


        String url = String.format(wechatConfig.getOauth2Url(), wechatConfig.getGzhAppid(), "snsapi_userinfo", redirectUrl);


        response.sendRedirect(url);
    }

    @GetMapping("wechat/redirect/")
    public void wechatRedirect(HttpServletRequest request, HttpServletResponse response, @RequestParam(name = "code", required = true) String code, HttpSession httpSession) throws IOException {
        String url = String.format(wechatConfig.getOauth2AccessTokenUrl(), wechatConfig.getGzhAppid(), wechatConfig.getGzhSecret(), code);

        RestTemplate template = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity entity = new HttpEntity<>(headers);


        String data = template.exchange(url, HttpMethod.GET, entity, String.class).getBody();


        ObjectMapper objectMapper = new ObjectMapper();

        try {
            HashMap responseMap = objectMapper.readValue(data, HashMap.class);

            if(!responseMap.containsKey("errcode")) {
                httpSession.setAttribute("openid", responseMap.get("openid"));
                httpSession.setAttribute("wx:access_token", responseMap.get("access_token"));
            }

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }


//        URL urlObj = new URL(request.getRequestURL().toString());
//        String protocol = urlObj.getProtocol(); // 获取协议（如http, https）
//        String host = urlObj.getHost(); // 获取主机名（域名）
//        String redirectUrl = protocol + "://" + host;
//
//        response.sendRedirect(redirectUrl);


        String redirectUrl = APP_HOST;

        if(!contextPath.isEmpty()) {
            redirectUrl += contextPath;
        }

        redirectUrl += "/auth/auth";

        response.sendRedirect(redirectUrl);
    }

    @GetMapping("logout")
    public void logout(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession, @RequestAttribute("role") String role, @RequestAttribute("userId") Long userId) throws IOException {
        httpSession.removeAttribute("userId");
        httpSession.removeAttribute(authStatusKey);

        httpSession.invalidate();

        if(Objects.equals(role, UserRoleType.Teacher)) {
            db.teacher.update(new LambdaUpdateWrapper<Teacher>().set(Teacher::getOpenid, "").eq(Teacher::getId, userId));
        }

        if(Objects.equals(role, UserRoleType.Student)) {
            db.student.update(new LambdaUpdateWrapper<Student>().set(Student::getOpenid, "").eq(Student::getId, userId));
        }

        if(Objects.equals(role, UserRoleType.Other)) {
            db.otherUser.update(new LambdaUpdateWrapper<OtherUser>().set(OtherUser::getOpenid, "").eq(OtherUser::getId, userId));
        }


        URL urlObj = new URL(request.getRequestURL().toString());
        String protocol = urlObj.getProtocol(); // 获取协议（如http, https）
        String host = urlObj.getHost(); // 获取主机名（域名）
        String redirectUrl = protocol + "://" + host;

//        if(!contextPath.isEmpty()) {
//            redirectUrl += contextPath;
//        }

        //redirectUrl += "/auth/wechat/redirect/";
        redirectUrl = URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8);



        String url = String.format(logoutUrl, "");

        System.out.println(url);

        response.sendRedirect(url);
    }

    @GetMapping("auth")
    public void auth(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession) throws IOException {
        Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        System.out.println("回调---------------");
        if(assertion != null) {
            Principal principal  = assertion.getPrincipal();

            System.out.println("---------principal-----------");
            System.out.println(principal);

            String loginName = principal.getName();


            Instant now = Instant.now();
            long time = now.getEpochSecond();

            PortalLoginLog log = new PortalLoginLog();
            log.setIp(IpUtil.getIpAddr(request));
            log.setTime(time);
            log.setBrowser(request.getHeader("User-Agent"));
            log.setAccount(loginName);
            log.setStatus(false);
            log.setType("移动端");


            String address = authService.getLocation(log.getIp());
            if(address != null) {
                log.setLocation(address);
            }

            try{

                String avatar = "";

                String openid = "";
                Object Opendid = httpSession.getAttribute("openid");
                if(Opendid != null) {
                    openid = (String) Opendid;
                }


                String access_token = "";
                Object Accesstoken = httpSession.getAttribute("wx:access_token");
                if(Accesstoken != null) {
                    access_token = (String) Accesstoken;
                }


                if(!openid.isEmpty()) {
                    Users users = db.users.getOne(new LambdaQueryWrapper<Users>().eq(Users::getOpenid, openid));

                    if(users != null) {
                        //1：教职工，2：学生，3：其它
                        if(users.getUserRole() == 1) {
                            db.teacher.update(new LambdaUpdateWrapper<Teacher>().set(Teacher::getOpenid, "").set(Teacher::getWxheadimgurl, "").eq(Teacher::getId, users.getSourceId()));
                        }else if(users.getUserRole() == 2) {
                            db.student.update(new LambdaUpdateWrapper<Student>().set(Student::getOpenid, "").set(Student::getWxheadimgurl, "").eq(Student::getId, users.getSourceId()));
                        }else if(users.getUserRole() == 3) {
                            db.otherUser.update(new LambdaUpdateWrapper<OtherUser>().set(OtherUser::getOpenid, "").set(OtherUser::getWxheadimgurl, "").eq(OtherUser::getId, users.getSourceId()));
                        }
                    }

                    String url = String.format(wechatConfig.getUserinfoUrl(), access_token,openid);

                    RestTemplate template = new RestTemplate();
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);

                    HttpEntity entity = new HttpEntity<>(headers);


                    String data = template.exchange(url, HttpMethod.GET, entity, String.class).getBody();


                    ObjectMapper objectMapper = new ObjectMapper();

                    try {
                        HashMap responseMap = objectMapper.readValue(data, HashMap.class);

                        if(!responseMap.containsKey("errcode")) {
                            avatar = (String) responseMap.get("headimgurl");
                        }

                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                }


                boolean f = false;

                Long id = 0L;
                String role = "";
                HashMap<String, Object> userInfo = new HashMap<>();
                userInfo.put("avatar", avatar);


                Teacher teacher = db.teacher.getOne(new LambdaQueryWrapper<Teacher>().eq(Teacher::getGh, loginName));
                if(teacher != null) {
                    f = true;
                    id = teacher.getId();
                    role = UserRoleType.Teacher;

                    userInfo.put("name", teacher.getName());
                    userInfo.put("sex", teacher.getSex());
                    userInfo.put("gh", teacher.getGh());
                    userInfo.put("jobPost", teacher.getJobPost());
                    userInfo.put("dept", teacher.getDept());


                    if(teacher.getOpenid().isEmpty() || teacher.getWxheadimgurl().isEmpty() || !teacher.getOpenid().equals(openid)) {
                        LambdaUpdateWrapper<Teacher> wrapper = new LambdaUpdateWrapper<>();
                        wrapper.eq(Teacher::getId, teacher.getId());
                        wrapper.set(Teacher::getOpenid, openid);
                        wrapper.set(Teacher::getWxheadimgurl, avatar);

                        db.teacher.update(wrapper);
                    }
                }

                if(!f) {
                    Student student = db.student.getOne(new LambdaQueryWrapper<Student>().eq(Student::getXh, loginName));
                    if(student != null) {
                        f = true;

                        id = student.getId();
                        role = UserRoleType.Student;

                        userInfo.put("name", student.getName());
                        userInfo.put("sex", student.getSex());
                        userInfo.put("xh", student.getXh());
                        userInfo.put("grade", student.getGrade());
                        userInfo.put("class", student.getClassNo());



                        if(student.getOpenid().isEmpty() || student.getWxheadimgurl().isEmpty() || !student.getOpenid().equals(openid)) {
                            LambdaUpdateWrapper<Student> wrapper = new LambdaUpdateWrapper<>();
                            wrapper.eq(Student::getId, student.getId());
                            wrapper.set(Student::getOpenid, openid);
                            wrapper.set(Student::getWxheadimgurl, avatar);

                            db.student.update(wrapper);
                        }
                    }
                }

                if(!f) {
                    OtherUser otherUser = db.otherUser.getOne(new LambdaQueryWrapper<OtherUser>().eq(OtherUser::getGh, loginName));
                    if(otherUser != null) {
                        f = true;
                        id = otherUser.getId();
                        role = UserRoleType.Other;

                        userInfo.put("name", otherUser.getName());
                        userInfo.put("sex", otherUser.getSex());
                        userInfo.put("gh", otherUser.getGh());
                        userInfo.put("jobPost", otherUser.getJobPost());


                        if(otherUser.getOpenid().isEmpty() || otherUser.getWxheadimgurl().isEmpty() || !otherUser.getOpenid().equals(openid)) {
                            LambdaUpdateWrapper<OtherUser> wrapper = new LambdaUpdateWrapper<>();
                            wrapper.eq(OtherUser::getId, otherUser.getId());
                            wrapper.set(OtherUser::getOpenid, openid);
                            wrapper.set(OtherUser::getWxheadimgurl, avatar);

                            db.otherUser.update(wrapper);
                        }
                    }
                }

                //String token = authService.makeToken(id, role, loginName, time);


                Map<String, Object> res = new HashMap<>();
                //res.put("token", token);
                //res.put("expire", authService.getJwtExpire());

                res.put("role", role);
                res.put("info", userInfo);


                httpSession.setAttribute(authStatusKey, 1);
                httpSession.setAttribute("role", role);
                httpSession.setAttribute("userInfo", userInfo);
                httpSession.setAttribute("userId", id);
                httpSession.setAttribute("userKey", loginName);

                log.setStatus(true);

                URL urlObj = new URL(request.getRequestURL().toString());
                String protocol = urlObj.getProtocol(); // 获取协议（如http, https）
                String host = urlObj.getHost(); // 获取主机名（域名）
                String redirectUrl = protocol + "://" + host;

                response.sendRedirect(redirectUrl);

            }catch (Exception e) {

            }finally {
                userLoginLogRepository.insert(log);
            }

        }
    }


    @PostMapping("login")
    public Object login(@RequestBody LoginDto dto, HttpServletRequest request, HttpSession httpSession){



        if(dto.getUsername() == null || dto.getPassword() == null || dto.getUsername().isEmpty() || dto.getPassword().isEmpty()) {
            return ResponseUtil.failRes();
        }

        Instant now = Instant.now();
        long time = now.getEpochSecond();

        PortalLoginLog log = new PortalLoginLog();
        log.setIp(IpUtil.getIpAddr(request));
        log.setTime(time);
        log.setBrowser(request.getHeader("User-Agent"));
        log.setAccount(dto.getUsername());
        log.setStatus(false);
        log.setType("移动端");
        log.setLocation("四川");

        try{
            String username = openapi.login(dto.getUsername(), dto.getPassword());
            if(Objects.equals(username, dto.getUsername())) {

                String avatar = "";

                String openid = "";
                Object Opendid = httpSession.getAttribute("openid");
                if(Opendid != null) {
                    openid = (String) Opendid;
                }


                String access_token = "";
                Object Accesstoken = httpSession.getAttribute("wx:access_token");
                if(Accesstoken != null) {
                    access_token = (String) Accesstoken;
                }


                if(!openid.isEmpty()) {
                    String url = String.format(wechatConfig.getUserinfoUrl(), access_token,openid);

                    RestTemplate template = new RestTemplate();
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);

                    HttpEntity entity = new HttpEntity<>(headers);


                    String data = template.exchange(url, HttpMethod.GET, entity, String.class).getBody();


                    ObjectMapper objectMapper = new ObjectMapper();

                    try {
                        HashMap responseMap = objectMapper.readValue(data, HashMap.class);

                        if(!responseMap.containsKey("errcode")) {
                            avatar = (String) responseMap.get("headimgurl");
                        }

                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                }




                boolean f = false;

                Long id = 0L;
                String role = "";
                HashMap<String, Object> userInfo = new HashMap<>();
                userInfo.put("avatar", avatar);


                Teacher teacher = db.teacher.getOne(new LambdaQueryWrapper<Teacher>().eq(Teacher::getGh, username));
                if(teacher != null) {
                    f = true;
                    id = teacher.getId();
                    role = UserRoleType.Teacher;

                    userInfo.put("name", teacher.getName());
                    userInfo.put("sex", teacher.getSex());
                    userInfo.put("gh", teacher.getGh());
                    userInfo.put("jobPost", teacher.getJobPost());


                    if(teacher.getOpenid().isEmpty() || teacher.getWxheadimgurl().isEmpty()) {
                        LambdaUpdateWrapper<Teacher> wrapper = new LambdaUpdateWrapper<>();
                        wrapper.eq(Teacher::getId, teacher.getId());
                        if(teacher.getOpenid().isEmpty()) {
                            wrapper.set(Teacher::getOpenid, openid);
                        }
                        wrapper.set(Teacher::getWxheadimgurl, avatar);

                        db.teacher.update(wrapper);
                    }
                }

                if(!f) {
                    Student student = db.student.getOne(new LambdaQueryWrapper<Student>().eq(Student::getXh, username));
                    if(student != null) {
                        f = true;

                        id = student.getId();
                        role = UserRoleType.Student;

                        userInfo.put("name", student.getName());
                        userInfo.put("sex", student.getSex());
                        userInfo.put("xh", student.getXh());
                        userInfo.put("grade", student.getGrade());
                        userInfo.put("class", student.getClassNo());



                        if(student.getOpenid().isEmpty() || student.getWxheadimgurl().isEmpty()) {
                            LambdaUpdateWrapper<Student> wrapper = new LambdaUpdateWrapper<>();
                            wrapper.eq(Student::getId, student.getId());
                            if(student.getOpenid().isEmpty()) {
                                wrapper.set(Student::getOpenid, openid);
                            }
                            wrapper.set(Student::getWxheadimgurl, avatar);

                            db.student.update(wrapper);
                        }
                    }
                }

                if(!f) {
                    OtherUser otherUser = db.otherUser.getOne(new LambdaQueryWrapper<OtherUser>().eq(OtherUser::getGh, username));
                    if(otherUser != null) {
                        f = true;
                        id = otherUser.getId();
                        role = UserRoleType.Other;

                        userInfo.put("name", otherUser.getName());
                        userInfo.put("sex", otherUser.getSex());
                        userInfo.put("gh", otherUser.getGh());
                        userInfo.put("jobPost", otherUser.getJobPost());


                        if(otherUser.getOpenid().isEmpty() || otherUser.getWxheadimgurl().isEmpty()) {
                            LambdaUpdateWrapper<OtherUser> wrapper = new LambdaUpdateWrapper<>();
                            wrapper.eq(OtherUser::getId, otherUser.getId());
                            if(otherUser.getOpenid().isEmpty()) {
                                wrapper.set(OtherUser::getOpenid, openid);
                            }
                            wrapper.set(OtherUser::getWxheadimgurl, avatar);

                            db.otherUser.update(wrapper);
                        }
                    }
                }

                if(!f) {
                    return ResponseUtil.failRes("系统无此用户");
                }

//                if(time > 0) {
//                    String[] keys = wechatConfig.getMsgTemplateFields().split(",");
//                    HashMap<String, HashMap<String, Object>> msgData = new HashMap<>();
//                    String[] values = {"特别事项", "2021-02-03"};
//                    for(int i = 0; i < keys.length; i ++) {
//                        HashMap<String, Object> item = new HashMap<>();
//                        item.put("value", values[i]);
//                        msgData.put(keys[i], item);
//                    }
//                    if(openid == null) {
//                        openid = "oOURH63wqO7Pcg2dtMQnyMK9_0Jc";
//                    }
//                    wechatapi.sendMsg(openid, msgData);
//                }



                String token = authService.makeToken(id, role, dto.getUsername(), time);

                Map<String, Object> res = new HashMap<>();
                res.put("token", token);
                res.put("expire", authService.getJwtExpire());
                res.put("role", role);
                res.put("info", userInfo);

                log.setStatus(true);


                return ResponseUtil.successRes(res);
            }
        }catch (Exception e) {
            System.out.println(e.getMessage());
        }finally {
            userLoginLogRepository.insert(log);
        }


        return ResponseUtil.failRes("账号或密码错误");

    }

}
